Skip to content

[generate] Slice cached decoder inputs of encoder-decoder models without decoder mask - #50013

Closed
tarekziade wants to merge 1 commit into
mainfrom
fix-encdec-prefill-cache-slicing
Closed

tarekziade wants to merge 1 commit into
mainfrom
fix-encdec-prefill-cache-slicing

Conversation

@tarekziade

@tarekziade tarekziade commented Oct 27, 2026 •

Copy link
Copy Markdown
Collaborator

🤗 Transformers CI

Fixes #50011

test_validate_assistant (Whisper + distil-whisper assistant) triggers a device-side assert that takes down every later test in the worker.

Cause: when generate restarts from a cache, _prefill only slices off the cached inputs if it knows the mask length. Encoder-decoder models have no decoder mask, and _mask_length (#48814) is only set for decoder-only. So an encoder-decoder assistant re-prefills the full decoder_input_ids every drafting round, its cache doubles, and Whisper indexes position 448 (max is 447).

Fix: for encoder-decoder without a decoder mask, treat decoder_input_ids as the full sequence when longer than the cache. Added a tiny-BART test (fails on main, passes here); the slow test passes locally.

🤖 Generated with Claude Code

…out decoder mask

When `generate` restarts from an existing cache, `_prefill` only slices the already-cached inputs when it knows the
mask length. Encoder-decoder models usually have no `decoder_attention_mask` (Whisper even pops it), and
`_mask_length` is only recorded for decoder-only models, so the FULL `decoder_input_ids` were processed again on
top of the cache.

This hits encoder-decoder assistants in assisted decoding: the assistant cache grows by the full sequence at every
drafting round, until Whisper's decoder indexes past its 448 learned positions (device-side assert on CUDA, which
then poisons every following test of the worker).

Fixes #50011

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@tarekziade

Copy link
Copy Markdown
Collaborator Author

run-slow: whisper, bart, t5, mbart, marian, pegasus, m2m_100, bigbird_pegasus, t5gemma, seamless_m4t, moonshine, encoder_decoder, speech_encoder_decoder, vision_encoder_decoder

@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

@github-actions

Copy link
Copy Markdown
Contributor

CI (Nvidia + AMD)

Nvidia · ✅ No new failures 🎉👏 · ⚙️ Workflow · 📊 Dashboard

AMD · ✅ No new failures 🎉👏 · ⚙️ Workflow · 📊 Dashboard

@Cyrilvallez Cyrilvallez left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix is in general wrong, see my comment! For any small first generation loop (small prefix + small new number of tokens, it's very likely to have a subsequent prefill with more tokens than the existing Cache!
I opened #50027 to supersede this with a better fix!

Comment on lines +4296 to +4299
elif self.config.is_encoder_decoder:
# The decoder mask is usually absent (e.g. assistant models): the decoder inputs are the FULL sequence
# if they are longer than the cache
mask_length = input_ids.shape[1] if input_ids.shape[1] > past_length else -1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong, they may be longer than the Cache even when restarting, e.g. any small first prefil + generation with a longer subsequent prefill

@Cyrilvallez

Cyrilvallez commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Closing this in the meantime in favor of the linked PR! (Also note that most of the tests that are linked here are in fact passing on main, they appear as failed only because of the device-side Assert which fails all subsequent tests after it appears. I think that only tests/generation/test_utils.py::GenerationIntegrationTests::test_validate_assistant is really failing, and it has been failing a very long time from what I can see 🥲 (before we started dropping the attention mask early in #48814 at least)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

CUDA device-side assert triggered in 31 generation tests

3 participants